/*
 * Copyright (C) 2008-2008 LeGACY <http://code.google.com/p/legacy-project/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __LEGACY_ITEM_H
#define __LEGACY_ITEM_H

#include "Common.h"
#include "Object.h"
#include "ItemPrototype.h"

struct SpellEntry;
class Pet;
class QueryResult;

typedef struct
{
	uint32 setid;
	uint32 item_count;
	SpellEntry const *spells[8];
} ItemSetEffect;

enum InventoryChangeFailure
{
	EQUIP_ERR_OK                                 = 0,
	EQUIP_ERR_CANT_EQUIP_LEVEL_I                 = 1,
	EQUIP_ERR_ERR_CANT_EQUIP_SKILL               = 2,
	EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT             = 3,
	EQUIP_ERR_BAG_FULL                           = 4,
    EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG        = 5,
    EQUIP_ERR_CANT_TRADE_EQUIP_BAGS              = 6,
    EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE              = 7,
    EQUIP_ERR_NO_REQUIRED_PROFICIENCY            = 8,
    EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE        = 9,
    EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM        = 10,
    EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM2       = 11,
    EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE2       = 12,
    EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED          = 13,
    EQUIP_ERR_CANT_DUAL_WIELD                    = 14,
    EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG            = 15,
    EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG2           = 16,
    EQUIP_ERR_CANT_CARRY_MORE_OF_THIS            = 17,
    EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE3       = 18,
    EQUIP_ERR_ITEM_CANT_STACK                    = 19,
    EQUIP_ERR_ITEM_CANT_BE_EQUIPPED              = 20,
    EQUIP_ERR_ITEMS_CANT_BE_SWAPPED              = 21,
    EQUIP_ERR_SLOT_IS_EMPTY                      = 22,
    EQUIP_ERR_ITEM_NOT_FOUND                     = 23,
    EQUIP_ERR_CANT_DROP_SOULBOUND                = 24,
    EQUIP_ERR_OUT_OF_RANGE                       = 25,
    EQUIP_ERR_TRIED_TO_SPLIT_MORE_THAN_COUNT     = 26,
    EQUIP_ERR_COULDNT_SPLIT_ITEMS                = 27,
    EQUIP_ERR_MISSING_REAGENT                    = 28,
    EQUIP_ERR_NOT_ENOUGH_MONEY                   = 29,
    EQUIP_ERR_NOT_A_BAG                          = 30,
    EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS        = 31,
    EQUIP_ERR_DONT_OWN_THAT_ITEM                 = 32,
    EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER             = 33,
    EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT        = 34,
    EQUIP_ERR_TOO_FAR_AWAY_FROM_BANK             = 35,
    EQUIP_ERR_ITEM_LOCKED                        = 36,
    EQUIP_ERR_YOU_ARE_STUNNED                    = 37,
    EQUIP_ERR_YOU_ARE_DEAD                       = 38,
    EQUIP_ERR_CANT_DO_RIGHT_NOW                  = 39,
    EQUIP_ERR_INT_BAG_ERROR                      = 40,
    EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER2            = 41,
    EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH          = 42,
    EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED          = 43,
    EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED           = 44,
    EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED            = 45,
    EQUIP_ERR_BOUND_CANT_BE_WRAPPED              = 46,
    EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED             = 47,
    EQUIP_ERR_BAGS_CANT_BE_WRAPPED               = 48,
	EQUIP_ERR_ALREADY_LOOTED                     = 49,
    EQUIP_ERR_INVENTORY_FULL                     = 50,
    EQUIP_ERR_BANK_FULL                          = 51,
    EQUIP_ERR_ITEM_IS_CURRENTLY_SOLD_OUT         = 52,
    EQUIP_ERR_BAG_FULL3                          = 53,
    EQUIP_ERR_ITEM_NOT_FOUND2                    = 54,
    EQUIP_ERR_ITEM_CANT_STACK2                   = 55,
    EQUIP_ERR_BAG_FULL4                          = 56,
    EQUIP_ERR_ITEM_SOLD_OUT                      = 57,
    EQUIP_ERR_OBJECT_IS_BUSY                     = 58,
    EQUIP_ERR_NONE                               = 59,
    EQUIP_ERR_NOT_IN_COMBAT                      = 60,
    EQUIP_ERR_NOT_WHILE_DISARMED                 = 61,
    EQUIP_ERR_BAG_FULL6                          = 62,
    EQUIP_ERR_CANT_EQUIP_RANK                    = 63,
    EQUIP_ERR_CANT_EQUIP_REPUTATION              = 64,
    EQUIP_ERR_TOO_MANY_SPECIAL_BAGS              = 65,
    EQUIP_ERR_LOOT_CANT_LOOT_THAT_NOW            = 66,
    EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE              = 67,
    EQUIP_ERR_VENDOR_MISSING_TURNINS             = 68,
    EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS            = 69,
    EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS            = 70,
    EQUIP_ERR_ITEM_MAX_COUNT_SOCKETED            = 71,
    EQUIP_ERR_MAIL_BOUND_ITEM                    = 72,
    EQUIP_ERR_NO_SPLIT_WHILE_PROSPECTING         = 73,
    EQUIP_ERR_ITEM_MAX_COUNT_EQUIPPED_SOCKETED   = 75,
    EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED    = 76,
    EQUIP_ERR_TOO_MUCH_GOLD                      = 77,
    EQUIP_ERR_NOT_DURING_ARENA_MATCH             = 78,
    EQUIP_ERR_CANNOT_TRADE_THAT                  = 79,
    EQUIP_ERR_PERSONAL_ARENA_RATING_TOO_LOW      = 80
};

enum BuyFailure
{
	BUY_ERR_CANT_FIND_ITEM                               = 0,
	BUY_ERR_ITEM_ALREADY_SOLD                            = 1,
	BUY_ERR_NOT_ENOUGH_MONEY                             = 2,
	BUY_ERR_DISTANCE_TOO_FAR                             = 3,
	BUY_ERR_CANT_CARRY_MORE                              = 4
};

enum SellFailure
{
	SELL_ERR_CANT_FIND_ITEM                              = 0,
	SELL_ERR_CANT_SELL_ITEM                              = 1,
	SELL_ERR_CANT_FIND_VENDOR                            = 2,
	SELL_ERR_YOU_DONT_OWN_THAT_ITEM                      = 3
};

enum ItemUpdateState
{
	ITEM_UNCHANGED                                 = 0,
	ITEM_CHANGED                                   = 1,
	ITEM_NEW                                       = 2,
	ITEM_REMOVED                                   = 3
};

class LEGACY_DLL_SPEC Item : public Object
{
	public:
		Item();

		virtual bool Create(uint32 guidlow, uint32 itemid, Player* owner);

		ItemPrototype const* GetProto() const;
		uint16 const GetModelId() const { return uint16(GetProto()->modelid); }

		uint64 const& GetOwnerGUID() const { return GetUInt64Value(ITEM_FIELD_OWNER); }
		void SetOwnerGUID(uint64 guid) { SetUInt64Value(ITEM_FIELD_OWNER, guid); }

		Player* GetOwner() const;

		virtual void SaveToDB();
		virtual bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result = NULL);
		virtual void DeleteFromDB();
		void DeleteFromInventoryDB();

		//bool IsBag() const { return GetProto()->InventoryType == INVTYPE_BAG; }

		bool CanBeTraded() const;

		uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); }
		uint32 GetCount() const { return GetUInt32Value(ITEM_FIELD_STACK_COUNT); }
		void SetCount(uint32 value) { SetUInt32Value(ITEM_FIELD_STACK_COUNT, value); }
		uint32 GetMaxStackCount() const { return GetProto()->Stackable ? GetProto()->Stackable : 1; }
		uint8 GetGemCountWithID(uint32 GemID) const {}

		uint8 GetSlot() const { return m_slot; }
		Pet *GetContainer() { return m_container; }
		//uint8 GetBagSlot() const;
		void SetSlot(uint8 slot) { m_slot = slot; }
		//uint16 GetPos() const { return uint16(GetBagSlot()) << 8 | GetSlot(); }
		void SetContainer(Pet *container) { m_container = container; }
		//bool CanGoIntoBag(ItemPrototype const *pBagProto);

		bool IsInPet() const { return m_container != NULL; }
		bool IsEquipped() const;

		void SendTimeUpdate(Player* owner);

		bool IsBroken() { return false; }

		// Update States
		ItemUpdateState GetState() const { return uState; }
		void SetState(ItemUpdateState state, Player *forplayer = NULL);
		void AddToUpdateQueueOf(Player *player);
		void RemoveFromUpdateQueueOf(Player *player);
		bool IsInUpdateQueue() const { return uQueuePos != -1; }
		uint16 GetQueuePos() const { return uQueuePos; }
		void FSetState(ItemUpdateState state)       // forced
		{
			uState = state;
		}

		void DumpItem();

	private:
		uint8 m_slot;
		Pet  *m_container;
		ItemUpdateState uState;
		int16 uQueuePos;
		bool  mb_in_trade;          // true if item is currently in trade-window
};
#endif
